package com.orange.notificationsummary.event.db;

import java.util.Map;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;

import com.orange.notificationsummary.R;
import com.orange.notificationsummary.utils.LogHelper;

public class NotificationDBHelper {
	private static final String	TAG				= "NotificationDBHelper";

	private static final Uri	URI_SMS_INBOX	= Uri.parse("content://sms");
	private static final Uri	URI_MMS_INBOX	= Uri.parse("content://mms");

	private static final String	UNKNOWN_NUMBER	= "-";

	/**
	 * get contact id by number
	 * 
	 * @param number
	 * @return
	 */
	public static String getContactId(Context context, String number) {
		Cursor c = null;
		try {
			c = context.getContentResolver().query(Phone.CONTENT_URI,
					new String[] { Phone.CONTACT_ID, Phone.NUMBER }, null,
					null, null);
			if (c != null && c.moveToFirst()) {
				while (!c.isAfterLast()) {
					if (PhoneNumberUtils.compare(number, c.getString(1))) {
						return c.getString(0);
					}
					c.moveToNext();
				}
			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getContactId. ", e);
		} finally {
			if (c != null) {
				c.close();
			}
		}
		return null;
	}

	/**
	 * get contact id by phone number according cursor
	 * 
	 * @param allPhoneNumber
	 *            ,phone number and contact cursor,value must from function
	 *            getAllPhoneNumberCursor
	 * @param numberContactMap
	 *            :HashMap,saving contact and phone number mapping relation
	 * @param phoneNumber
	 * @return
	 */
	public static String getContactIdByPhoneNumber(Context context,
			String phoneNumber, Cursor allPhoneNumber,
			Map<String, String> numberContactMap) {
		if (TextUtils.isEmpty(phoneNumber)) {
			return null;
		}
		String contactId = null;
		if (numberContactMap != null
				&& numberContactMap.containsKey(phoneNumber)) {
			contactId = numberContactMap.get(phoneNumber);
		} else {
			if (allPhoneNumber == null) {
				contactId = getContactId(context, phoneNumber);
				if (numberContactMap != null) {
					numberContactMap.put(phoneNumber, contactId);
				}
			} else if (allPhoneNumber.moveToFirst()) {
				int indexNumber = allPhoneNumber
						.getColumnIndexOrThrow(Phone.NUMBER);
				int indexContactId = allPhoneNumber
						.getColumnIndexOrThrow(Phone.CONTACT_ID);
				while (!allPhoneNumber.isAfterLast()) {
					if (PhoneNumberUtils.compare(phoneNumber,
							allPhoneNumber.getString(indexNumber))) {
						String value = allPhoneNumber.getString(indexContactId);
						if (numberContactMap != null) {
							numberContactMap.put(phoneNumber, value);
						}
						return value;
					}
					allPhoneNumber.moveToNext();
				}
			}
		}
		return contactId;
	}

	/**
	 * get all phone number information,save in cursor
	 * 
	 * @param context
	 * @return
	 */
	public static Cursor getAllPhoneNumberCursor(Context context) {
		if (context == null) {
			return null;
		} else {
			return context.getContentResolver().query(Phone.CONTENT_URI,
					new String[] { Phone.CONTACT_ID, Phone.NUMBER }, null,
					null, null);
		}
	}

	/**
	 * get contact photo
	 * 
	 * @param contactId
	 * @return
	 */
	public static Bitmap getContactsPhoto(Context context, String contactId) {
		Cursor c = null;
		// load icon
		byte[] icon = null;
		try {
			// get contact photo URI
			Uri refUri = Uri.withAppendedPath(Contacts.CONTENT_URI, contactId);
			refUri = Uri.withAppendedPath(refUri,
					ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);

			// get cursor
			c = context.getContentResolver().query(refUri,
					new String[] { Photo.PHOTO }, null, null, null);

			if (c != null && c.moveToFirst()) {
				icon = loadContactPhoto(c, 0);
			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getContactsPhoto. ", e);
		} finally {
			if (c != null) {
				c.close();
			}
		}
		if (icon != null) {
			try {
				return BitmapFactory.decodeByteArray(icon, 0, icon.length);
			} catch (OutOfMemoryError e) {
				LogHelper.e(TAG, "getContactsPhoto. ", e);
				System.gc();
				return null;
			}
		}
		return null;
	}

	/**
	 * get contact photo by contactId,is map is not null,get value from map
	 * first
	 * 
	 * @param contactId
	 * @param map
	 * @return
	 */
	public static Bitmap getContactPhotoByContactId(Context context,
			String contactId, Map<String, Bitmap> map) {
		if (TextUtils.isEmpty(contactId)) {
			return null;
		}
		if (map != null && map.containsKey(contactId)) {
			return map.get(contactId);
		} else {
			Bitmap bitmap = getContactsPhoto(context, contactId);
			if (map != null) {
				map.put(contactId, bitmap);
				return bitmap;
			}
		}
		return null;
	}

	/**
	 * get contact photo
	 * 
	 * @param cursor
	 * @param bitmapColumnIndex
	 * @return
	 */
	private static byte[] loadContactPhoto(Cursor cursor, int bitmapColumnIndex) {
		return cursor.getBlob(bitmapColumnIndex);
	}

	/**
	 * get contact name
	 * 
	 * @param contacts_id
	 * @return
	 */
	private static String getDisplayName(Context context, String contacts_id) {
		Cursor c = null;
		try {
			c = context.getContentResolver().query(Contacts.CONTENT_URI,
					new String[] { Contacts.DISPLAY_NAME },
					Contacts._ID + "=" + contacts_id, null, null);
			if (c != null && c.moveToFirst()) {
				return c.getString(0);
			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getDisplayName. ", e);
		} finally {
			if (c != null) {
				c.close();
			}
		}
		return null;
	}

	public static String getDisplayNameByNumber(Context context, String number) {
		String displayName = "";

		String[] CONTACTOR_PROJECTION = new String[] { Phone.NUMBER,
				Phone.DISPLAY_NAME };
		String CONTACTOR_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER
				+ ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE
				+ "'";

		if (number != null && number.length() != 0) {
			if (number.startsWith(UNKNOWN_NUMBER)) {
				displayName = context.getString(R.string.from_unknown);
			} else {
				displayName = numberFormat(number);
				Cursor cursor = null;
				try {
					cursor = context.getContentResolver().query(
							Data.CONTENT_URI, CONTACTOR_PROJECTION,
							CONTACTOR_SELECTION, new String[] { number }, null);

					if (cursor.moveToFirst()) {
						displayName = cursor.getString(1);
					}
				} catch (Exception e) {
					LogHelper.e(TAG, "getDisplayNameByNumber. ", e);
				} finally {
					if (cursor != null)
						cursor.close();
				}
			}
		}
		return displayName;
	}

	private static String numberFormat(String number) {
		String numberRslt = "";
		if (!TextUtils.isEmpty(number)) {
			numberRslt = PhoneNumberUtils.formatNumber(number);
		}
		return numberRslt;
	}

	/**
	 * get phone numbers
	 * 
	 * @param contactId
	 * @return
	 */
	public static int getContactNumberCount(Context context, String contactId) {
		int count = 0;
		Cursor c = null;
		try {
			c = context
					.getContentResolver()
					.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
							new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER },
							ContactsContract.CommonDataKinds.Phone.CONTACT_ID
									+ " = " + contactId, null, null);
			if (c != null && c.moveToFirst()) {
				count = c.getCount();
			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getContactNumberCount. ", e);
		} finally {
			if (c != null) {
				c.close();
			}
		}
		return count;
	}

	/**
	 * get phone number type
	 * 
	 * @param number
	 * @return
	 */
	public static String getNumberType(Context context, String number) {
		Cursor c = null;
		try {
			c = context.getContentResolver().query(Phone.CONTENT_URI,
					new String[] { Phone.TYPE, Phone.LABEL, Phone.NUMBER },
					null, null, null);
			if (c != null && c.moveToFirst()) {
				while (!c.isAfterLast()) {
					if (PhoneNumberUtils.compare(c.getString(2), number)) {
						return Phone.getTypeLabel(context.getResources(),
								c.getInt(0), c.getString(1)).toString();
					}
					c.moveToNext();
				}
			}
		} catch (Exception e) {
			LogHelper.e(TAG, "getNumberType. ", e);
		} finally {
			if (c != null) {
				c.close();
			}
		}
		return null;
	}

	/**
	 * update callLog status
	 * 
	 * @param context
	 * @param _ids
	 * @return
	 */
	public static boolean updateCallLogStatusByIds(Context context,
			String[] _ids) {
		int count = 0;
		try {
			String where = " ";
			for (int i = 0; i < _ids.length; i++) {
				if (" ".equals(where)) {
					where = where + CallLog.Calls._ID + "=? ";
				} else {
					where = where + " or " + CallLog.Calls._ID + "=? ";
				}
			}
			ContentValues values = new ContentValues();
			values.put(CallLog.Calls.NEW, Integer.valueOf(0));
			count = context.getContentResolver().update(
					CallLog.Calls.CONTENT_URI, values, where, _ids);
		} catch (Exception e) {
			return false;
		}
		if (count != 0) {
			return true;
		}
		return false;
	}

	/**
	 * update unread message status
	 * 
	 * @param context
	 * @param threadIds
	 * @return
	 */
	public static boolean updateUnreadMsgStatusByThreadIds(Context context,
			String[] threadIds) {
		int count = 0;
		try {
			String where = " ";
			for (int i = 0; i < threadIds.length; i++) {
				if (" ".equals(where)) {
					where = where + " thread_id=? ";
				} else {
					where = where + " or thread_id=? ";
				}
			}
			ContentValues values = new ContentValues();
			values.put("read", 1);
			count = context.getContentResolver().update(URI_SMS_INBOX, values,
					where, threadIds);
			count = context.getContentResolver().update(URI_MMS_INBOX, values,
					where, threadIds);

		} catch (Exception e) {
			return false;
		}
		if (count != 0) {
			return true;
		}
		return false;
	}

	/**
	 * update unread voicemail status
	 * 
	 * @param context
	 * @param threadIds
	 * @return
	 */
	public static boolean updateUnreadVoicemailStatusByThreadIds(
			Context context, String[] threadIds) {
		int count = 0;
		try {
			String where = " ";
			for (int i = 0; i < threadIds.length; i++) {
				if (" ".equals(where)) {
					where = where + " id=? ";
				} else {
					where = where + " or id=? ";
				}
			}
			ContentValues values = new ContentValues();
			values.put("status", 2);
			count = context.getContentResolver().update(
					VoiceMailDBHelper.URI_VOICE_MAIL, values, where, threadIds);
		} catch (Exception e) {
			return false;
		}
		if (count != 0) {
			return true;
		}
		return false;
	}

	/**
	 * get display name by contactId
	 * 
	 * @param contacts_id
	 * @param contactDisplayNameMap
	 * @return
	 */
	public static String getDisplayNameByMap(Context context,
			String contactsId, Map<String, String> contactDisplayNameMap) {
		if (TextUtils.isEmpty(contactsId))
			return null;

		if (contactDisplayNameMap != null
				&& contactDisplayNameMap.containsKey(contactsId)) {
			return contactDisplayNameMap.get(contactsId);
		} else {
			String displayName = getDisplayName(context, contactsId);
			if (contactDisplayNameMap != null) {
				contactDisplayNameMap.put(contactsId, displayName);
			}
			return displayName;
		}
	}

	/**
	 * get contact number count,if map is not null,get value from map first
	 * 
	 * @param contactId
	 * @param numberTypeMap
	 * @return
	 */
	public static int getContactNumberCountByMap(Context context,
			String contactId, Map<String, Integer> numberCountMap) {
		int count = 0;
		if (!TextUtils.isEmpty(contactId)) {
			if (numberCountMap != null && numberCountMap.containsKey(contactId)) {
				count = numberCountMap.get(contactId).intValue();
			} else {
				count = getContactNumberCount(context, contactId);
				if (numberCountMap != null) {
					numberCountMap.put(contactId, count);
				}
			}
		}
		return count;
	}

	/**
	 * get number type,if map is not null get value from map first
	 * 
	 * @param number
	 * @param numberTypeMap
	 * @return
	 */
	public static String getNumberTypeByMap(Context context, String number,
			Map<String, String> numberTypeMap) {
		if (TextUtils.isEmpty(number)) {
			return null;
		}

		if (numberTypeMap != null && numberTypeMap.containsKey(number)) {
			return numberTypeMap.get(number);
		} else {
			String type = getNumberType(context, number);
			if (numberTypeMap != null) {
				numberTypeMap.put(number, type);
			}
			return type;
		}
	}
}
